package com.fang.config;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


/**
 * 访问拦截器
 *
 * @author Fang Ruichuan
 * @date 2023-01-07 20:44
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class AccessLimiterInterceptor implements HandlerInterceptor {

    private final RedisTemplate<String, Object> redisTemplate;

    @Override
    public boolean preHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler) throws Exception {
        try {
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                // 获取方法
                Method method = handlerMethod.getMethod();
                // 是否有AccessLimit注解
                if (!method.isAnnotationPresent(AccessLimit.class)) {
                    return true;
                }
                // 获取注解内容信息
                AccessLimit accessLimit = method.getAnnotation(AccessLimit.class);
                if (Objects.isNull(accessLimit)) {
                    return true;
                }
                int seconds = accessLimit.second();
                int maxCount = accessLimit.maxCount();

                // 存储key
                String key = request.getRemoteAddr() + ":" + request.getContextPath() + ":" + request.getServletPath();

                // 已经访问的次数
                Integer count = (Integer) redisTemplate.opsForValue().get(key);
                System.out.println("已经访问的次数：" + count);
                if (Objects.isNull(count) || count.equals(-1)) {
                    redisTemplate.opsForValue().set(key, 1, seconds, TimeUnit.SECONDS);
                    return true;
                }
                if (count < maxCount) {
                    redisTemplate.opsForValue().increment(key);
                    return true;
                }
                if (count >= maxCount) {
                    log.warn("请求过于频繁，请稍后再试");
                    return false;
                }
            }
            return true;
        } catch (Exception e) {
            log.warn("请求过于频繁，请稍后再试");
        }
        return true;
    }
}
